package com.gs.synedocket.service;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.os.PowerManager;
import android.util.Log;
import android.widget.RemoteViews;

import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;

import com.google.gson.reflect.TypeToken;
import com.gs.synedocket.R;
import com.gs.synedocket.callback.SignalRCallBack;
import com.gs.synedocket.constant.AllConstants;
import com.gs.synedocket.db.dao.LogUtil;
import com.gs.synedocket.db.dto.PushDto;
import com.gs.synedocket.receiver.NotificationReceiver;
import com.gs.synedocket.signalr.SignalRCode;
import com.gs.synedocket.signalr.SignalRConn;
import com.gs.synedocket.signalr.SignalRException;
import com.gs.synedocket.util.GsonUtil;
import com.gs.synedocket.util.NotificationUtil;
import com.gs.synedocket.util.OKHttpUtil;
import com.gs.synedocket.util.StringUtil;

import java.util.Calendar;

public class SignalRService extends Service implements SignalRCallBack {
    private final static String HUB_URL = OKHttpUtil.SIGNAL_URL + "/api/broadcastHub";
    private final static long sleep = 4000;
    private static boolean isRunning = true;
    private boolean reconnection = false;
    private SignalRConn signalR;
    private int i = 0;
    private Thread thread;
    private PowerManager.WakeLock wakeLock;
    private PowerManager powerManager;
    private Notification.Builder mChannelBuilder;
    private NotificationCompat.Builder mBuilder;
    private String mContentTitle;

    public static void stopSignalR() {
        isRunning = false;
    }

    private void screenOn() {
        boolean isScreenOn = Build.VERSION.SDK_INT >= 20 ? powerManager.isInteractive() : powerManager.isScreenOn();
        if (!isScreenOn) {
            PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "synedocket:notificationLock");
            wl.acquire(3000);
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(AllConstants.TAG, "service onStartCommand");
        isRunning = true;
        if (wakeLock == null) {
            powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
            wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "synedocket:CPUKeepRunning");
            wakeLock.setReferenceCounted(true);
            Calendar c = Calendar.getInstance();
            c.setTimeInMillis(System.currentTimeMillis());
            int hour = c.get(Calendar.HOUR_OF_DAY);
            if (hour >= 23 || hour <= 6) {
                wakeLock.acquire(5000);
            } else {
                wakeLock.acquire(300000);
            }
        }
        if (signalR == null) {
            signalR = new SignalRConn(HUB_URL, this);
            signalRStart();
        }
        if (thread == null) {
            thread = new Thread(runnableSend);
            thread.start();
        }
        mContentTitle = getString(R.string.app_name);
        return START_STICKY;
    }

    private final Runnable runnableSend = new Runnable() {
        @Override
        public void run() {
            while (isRunning) {
                try {
                    Thread.sleep(sleep);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (reconnection) {
                    try {
                        reconnection = false;
                        if (signalR == null) break;
                        signalR.start();
                        Log.i(AllConstants.TAG, "start: Thread");
                    } catch (SignalRException e) {
                        reconnection = true;
                    }
                }
            }
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    @Override
    public void onDestroy() {
        if (wakeLock != null) {
            if (wakeLock.isHeld()) {
                wakeLock.release();
                wakeLock = null;
            }
        }
        if (signalR != null) {
            signalR.stopConnect();
            signalR = null;
        }
        if (thread != null) {
            thread = null;
        }
        Log.i(AllConstants.TAG, "service onDestroy");
        super.onDestroy();
    }

    /**
     * 发送通知
     */
    @SuppressLint("NotificationTrampoline")
    private void showNotification(PushDto<String> pushDto) {
        String title = StringUtil.getString(R.string.new_docket, pushDto.getData());
        i++;
        if (i > 11) {
            i = 1;
        }
        NotificationUtil.getInstance().getNotificationManager().cancel(i);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (mChannelBuilder == null) {
                NotificationChannel channel = NotificationUtil.getInstance().getChannel();
                NotificationUtil.getInstance().getNotificationManager().createNotificationChannel(channel);
                mChannelBuilder = NotificationUtil.getInstance().getNotification(this)
                        .setAutoCancel(true)
                        .setShowWhen(true)
                        .setVisibility(Notification.VISIBILITY_PUBLIC)
                        .setContentTitle(mContentTitle)
                        .setSmallIcon(R.drawable.logo);
            }
            mChannelBuilder.setWhen(System.currentTimeMillis())
                    .setContentText(title)
                    .setContentIntent(createIntent(i, pushDto.getId()))
                    .setCustomContentView(getNotificationView(title))
                    .setCustomHeadsUpContentView(getNotificationBigView(title))
                    .setCustomBigContentView(getNotificationBigView(title));
            NotificationUtil.getInstance().getNotificationManager().notify(i, mChannelBuilder.build());
        } else {
            if (mBuilder == null) {
                mBuilder = NotificationUtil.getInstance().getNotificationCompat(this)
                        .setAutoCancel(true)
                        .setShowWhen(true)
                        .setContentTitle(mContentTitle)
                        .setSmallIcon(R.drawable.logo)
                        .setPriority(Notification.PRIORITY_MAX)
                        .setDefaults(Notification.DEFAULT_ALL);
            }
            mBuilder.setWhen(System.currentTimeMillis())
                    .setContentText(title)
                    .setContentIntent(createIntent(i, pushDto.getId()))
                    .setCustomContentView(getNotificationView(title))
                    .setCustomHeadsUpContentView(getNotificationBigView(title))
                    .setCustomBigContentView(getNotificationBigView(title));
            NotificationUtil.getInstance().getNotificationManager().notify(i, mBuilder.build());
        }
    }

    /**
     * 获取自定义的通知
     *
     * @return
     */
    private RemoteViews getNotificationView(String title) {
        RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification_item);
        setTextViewText(remoteViews, title);
        return remoteViews;
    }

    private RemoteViews getNotificationBigView(String title) {
        RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification_big_item);
        setTextViewText(remoteViews, title);
        return remoteViews;
    }

    private void setTextViewText(RemoteViews remoteViews, String title) {
        remoteViews.setTextViewText(R.id.tv_title, title);
    }

    /**
     * 发送广播
     *
     * @return
     */
    private PendingIntent createIntent(int num, String id) {
        Intent intent = new Intent(this, NotificationReceiver.class);
        intent.setAction(NotificationReceiver.NOTIFY_ACTION);
        intent.putExtra(AllConstants.ID, id);
        return PendingIntent.getBroadcast(this, num, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    }

    @Override
    public void receiveMessage(String msgType, String msg) {
        if (msgType.equals(SignalRCode.PUSH)) {
            PushDto<String> pushDto = (PushDto<String>) GsonUtil.getInstance().fromJson(msg, new TypeToken<PushDto<String>>() {
            }.getType());
            LogUtil.getInstance().insertOrReplaceData("收到推送信息：" + pushDto.getData());
            screenOn();
            showNotification(pushDto);
        }
    }

    @Override
    public void signalRClosed() {
        if (isRunning) {
            reconnection = true;
        }
    }

    @Override
    public void signalRStart() {
        new Thread(() -> {
            try {
                signalR.start();
            } catch (SignalRException e) {
                e.printStackTrace();
                reconnection = true;
//            reconnection = false;
            }
        }).start();
    }
}
